package com.mdinfo.base.component;


import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.mdinfo.base.common.bean.CommonResult;
import com.mdinfo.base.common.bean.Ref;
import com.mdinfo.base.exception.OtherLoginException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * Created by superbone on 2017/11/19.
 * 全局异常处理 + controller 参数校验异常处理
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger("异常拦截");


    /**
     * 参数校验异常
     */
    @ResponseBody
    @ExceptionHandler(BindException.class)
    public CommonResult<?> bind(BindException e){
        logger.error("参数绑定校验异常");
        BindingResult bindingResult = e.getBindingResult();
        String message = bindError(bindingResult);
        CommonResult<?> error = Ref.paramError(message);
        return error;
    }

    /**
     * 参数校验异常
     */
    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResult<?> methodArgument(MethodArgumentNotValidException e){

        logger.error("参数校验错误");
        BindingResult bindingResult = e.getBindingResult();
        String message = bindError(bindingResult);
        CommonResult<?> error = Ref.paramError(message);
        return error;
    }

    /**
     * token过期异常
     */
    @ResponseBody
    @ExceptionHandler(TokenExpiredException.class)
    public CommonResult<?> tokenExpiredException(TokenExpiredException e){
        logger.error("token过期");
        return Ref.tokenError("该token已经过期");
    }

    /**
     * token校验错误
     */
    @ResponseBody
    @ExceptionHandler(JWTVerificationException.class)
    public CommonResult<?> JWTVerificationException(JWTVerificationException e){
        logger.error("token校验失败");
        return Ref.tokenError("token校验失败");
    }

    /**
     * 用户在其他地方登录
     */
    @ResponseBody
    @ExceptionHandler(OtherLoginException.class)
    public CommonResult<?> OtherLoginException(OtherLoginException e){
        logger.error("用户在其他地方登录");
        return Ref.otherLogin();
    }

    /**
     * 拦截全部的异常
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public CommonResult<?> exception(HttpServletRequest request, Exception e){
        e.printStackTrace();
        logger.error("服务器异常:" + e.getMessage());
        CommonResult<?> error = Ref.serverError(e.getMessage());
        return error;
    }

    private String bindError(BindingResult bindingResult){
        String message = "";
        if(bindingResult.hasErrors()){
            StringBuffer sb = new StringBuffer();
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            fieldErrors.forEach(fieldError -> {
                String field = fieldError.getField();
                String defaultMessage = fieldError.getDefaultMessage();
                fieldError.getClass();
                sb.append(field)
                        .append(":")
                        .append(defaultMessage)
                        .append("; ");
            });
            message = sb.toString();
        }
        return message;
    }
}
